package Scene;

import java.awt.event.KeyEvent;

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;

import scriptmodule.EventDefine;
import scriptmodule.scriptManager;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import device.device;
import Clock.Clock;
import Clock.IUpdate;
import GameObj.GameObject;
import Scene.Camera;
import Scene.PhyWorld;
import com.badlogic.gdx.physics.box2d.World; 
import com.badlogic.gdx.math.Vector2;
import device.InputManager;
import scriptmodule.scriptManager;
import scriptmodule.EventDefine;
import com.badlogic.gdx.math.Vector2;

public class Level extends InputManager implements IUpdate 
{
	public int nWidth;
	public int nHeight;
	
	public Layer[] arrLayers;
	public Camera camera;
	
	// five pixels represent 1 meter in physical world
	public float physcale = 5.0f;
	
	// game object that be touched
	public GameObject objTouched = null;
	
	public void Render(	SpriteBatch spriteBatch)
	{	
		for (int i = 0; i < arrLayers.length; ++i)
		{
			arrLayers[i].Render(spriteBatch, camera);			
		}		
	}
	
	public void LoadFromFile(String fileName)
	{
		FileHandle hFile = Gdx.files.internal(fileName);
		String data = hFile.readString();
		
		try
		{
			JSONObject json = new JSONObject(data);
			nWidth = json.getInt("w");
			nHeight = json.getInt("h");
			if (json.has("g"))
			{
				JSONArray jsonGravity = json.getJSONArray("g");
				if (jsonGravity != null)
				{
					PhyWorld.SetGravity(new Vector2((float)jsonGravity.getDouble(0), 
							(float)jsonGravity.getDouble(1)));				
				}						
			}
			
			if (json.has("physcale"))
			{
				physcale = (float)json.getDouble("physcale");						
			}

			JSONArray jsonLayers = json.getJSONArray("layers");
			
			arrLayers = new Layer[jsonLayers.length()];
			for(int i = 0; i < jsonLayers.length(); ++i)
			{
				JSONObject jsonLayer = jsonLayers.getJSONObject(i);
				arrLayers[i] = new Layer();
				arrLayers[i].Load(jsonLayer, this);
			}
		}
		catch(JSONException e)
		{
		
		}

		if (camera == null)
		{
			camera = new Camera();		
			camera.setViewSize(device.nWidth, device.nHeight, device.spriteBatch);
			
	
			camera.setViewRange(nWidth, nHeight);
			camera.setViewPos(device.nWidth / 2, device.nHeight/ 2);
			
		}

	}
	
	public 	void Update(Clock clock)
	{
		for (int i = 0; i < arrLayers.length; ++i)
		{
			arrLayers[i].Update(clock);
		}
		
		if (camera != null)
		{
			camera.Update(clock);
		}
	}

	public boolean touchDown (int x, int y, int pointer, int button)
	{
		objTouched = null;
		int nRevertY = device.nHeight - y; 

		for (int i = 0; i < arrLayers.length; ++i)
		{
			if (arrLayers[i].bMainLayer)
			{
				for(int j = 0; j < arrLayers[i].arrObjs.length; ++j)
				{
					Vector2 vLayerPos = arrLayers[i].Screen2Layer(new Vector2((float)x, (float)nRevertY), camera);
					objTouched = arrLayers[i].arrObjs[j];
					if (objTouched.GetCanProcMouse() && objTouched.GetAbsBB().contains(vLayerPos.x, vLayerPos.y))
					{
						System.out.print("trigger event EVT_OnTouchDown\n");
						// trigger event
						  
						boolean bProcessed = scriptManager.CallGameObjScript(objTouched, EventDefine.EVT_OnTouchDown,
								  objTouched, x, nRevertY, pointer,button);
						if (bProcessed)
						{
							break;							
						}						
					}
				}
				break;
			}
		}
		return true;
	}
	
	public boolean touchUp (int x, int y, int pointer, int button)
	{
		int nRevertY = device.nHeight - y; 
		if (objTouched != null && objTouched.GetCanProcMouse())
		{
			  scriptManager.CallGameObjScript(objTouched, EventDefine.EVT_OnTouchUp,
					  objTouched, x, nRevertY, pointer, button);
		}
		
		objTouched = null;
		return true;
	}

	/** Called when a finger or the mouse was dragged.
	 * 
	 * @param x The x coordinate
	 * @param y The y coordinate
	 * @param pointer the pointer for the event.
	 * @return whether the input was processed */
	public boolean touchDragged (int x, int y, int pointer)
	{
		int nRevertY = device.nHeight - y; 
		if (objTouched != null && objTouched.GetCanProcMouse())
		{

			  scriptManager.CallGameObjScript(objTouched, EventDefine.EVT_OnTouchMove,
					  objTouched, x, nRevertY, pointer);
		}
		
		return true;
	}
	
	public boolean keyDown (int keycode)
	{
		if (Input.Keys.RIGHT == keycode)
		{
			float x = camera.GetX();
			float y = camera.GetY();
			camera.setViewPos((x + 1), y);
			return true;
		}
		else if (Input.Keys.LEFT == keycode)
		{
			float x = camera.GetX();
			float y = camera.GetY();
			camera.setViewPos((x - 1), y);
			return true;
		}
		return false;
	}
}
